package com.zeldu.uaa.service;

import com.zeldu.common.exception.CustomException;
import com.zeldu.common.exception.ExceptionCast;
import com.zeldu.common.model.response.CommonCode;
import com.zeldu.uaa.DTO.AuthToken;
import com.zeldu.uaa.DTO.LoginRequestDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Map;

@Service
public class AuthServiceImpl implements AuthService {
    @Value("${auth.url}")
    String authUrl;
    @Autowired
    RestTemplate restTemplate;
    @Override
    public AuthToken login(LoginRequestDTO loginRequestDTO, String clientId, String clientSecret) throws CustomException {
        AuthToken authToken = this.applyToken(loginRequestDTO.getUsername(), loginRequestDTO.getPassword(),loginRequestDTO.getIdentity(), clientId, clientSecret);
        if (authToken==null){
            ExceptionCast.cast(CommonCode.AUTH_CREDENTIAL_ERROR);
        }
        return authToken;
    }

    private AuthToken applyToken(String username,String password,String identity,String cliendId,String clientSecret){
        LinkedMultiValueMap<String, String> header = new LinkedMultiValueMap<>();
        String httpBasic = getHttpBasic("c1", "secret");
        header.add("Authorization",httpBasic);
        header.add("identity",identity);

        //定义body
        LinkedMultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type","password");
        body.add("username",username);
        body.add("password",password);
        HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(body, header);
        //设置restTemplate远程调用时候，对400和401不让报错，正确返回数据
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                if(response.getRawStatusCode()!=400 && response.getRawStatusCode()!=401){
                    super.handleError(response);
                }
            }
        });
        ResponseEntity<Map> exchange = restTemplate.exchange(authUrl, HttpMethod.POST, httpEntity, Map.class);
        Map bodyMap = exchange.getBody();
        //    System.out.println(bodyMap);
        if (bodyMap==null||
                bodyMap.get("access_token")==null
                ||bodyMap.get("refresh_token")==null||bodyMap.get("jti")==null){
            if(bodyMap!=null && bodyMap.get("error_description")!=null){
                String error_description = (String) bodyMap.get("error_description");
                if(error_description.indexOf("UserDetailsService returned null")>=0){

                    ExceptionCast.cast(CommonCode.AUTH_ACCOUNT_NOTEXISTS);
                }else if(error_description.indexOf("坏的凭证")>=0){

                   ExceptionCast.cast(CommonCode.Wrong_TOken);
                }else  if(error_description.indexOf("用户名或密码错误")>=0){
                    ExceptionCast.cast(CommonCode.AUTH_CREDENTIAL_ERROR);
                }
            }

            return null;
        }
        AuthToken authToken = new AuthToken();
//        authToken.setAccess_token((String) bodyMap.get("jti"));
//        authToken.setJwt_token((String) bodyMap.get("access_token"));
//        authToken.setRefresh_token((String) bodyMap.get("refresh_token"));
        return authToken;

    }
    //获取httpbasic的串
    private String getHttpBasic(String clientId,String clientSecret){
        String string = clientId+":"+clientSecret;
        //将串进行base64编码
        byte[] encode = Base64Utils.encode(string.getBytes());
        return "Basic "+new String(encode);
    }
}
